package main

import (
	"fmt"
	"math"
)

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M() {
	if t == nil {//MARK 优雅处理nil
		fmt.Println("<nil>")
		return
	}
}

type F float64

func (f F) M() {
	fmt.Println(f)//MARK 这里接收interface{}空接口  就是所有类型
}

func main() {
	var i I
	describe(i)//(<nil>, <nil>) MARK 如果被调用会报错
	
	i = &T{"Hello"}//(&{Hello}, *main.T) MARK 在内部，接口值可以看做包含值和具体类型的元组(值,具体类型)
	describe(i)
	i.M()//Hello
	
	var a T
	fmt.Println(a)// {} MARK 值的零值是空对象
	var t *T//nil MARK 指针的零值是nil
	i = t//(<nil>, *main.T)
	describe(i)
	i.M()//<nil>
	
	i = F(math.Pi)//(3.141592653589793, main.F) MARK 就是 float64(1.1415925) 数值强转
	describe(i)
	i.M()//3.141592653589793
}

func describe(i I) {
	fmt.Printf("(%v, %T)\n", i, i)
}
